#pragma once
#include "Types.h"
#include "util/Singleton.h"

#include <iostream>



namespace Boon
{

	enum CommandStates
	{
		CMD_ST_UNUSED = 0x0,			// 0 set
		CMD_ST_RAISED = 0x1,			// 1st set
		CMD_ST_HOLD = 0x11,				// 4th and 1st bit set
		CMD_ST_CANCELED = 0x10			// 4th set, 1st not set
	};

	class Command
	{
	public:
		Command( const char* name ) : m_State( 0 ), m_Name( name ) { }

		/*
		 * 0x0000 0000		previous 0; current 0 -> unused
		 * 0x0000 0001		previous 0; current 1 -> banged
		 * 0x0001 0001		prevuous 1; current 1 -> hold
		 * 0x0001 0000		prevuous 1; current 0 -> cancel
		 */
		inline void			SetEnabled( bool flag )
		{
			m_State <<= 4; // setting current state to previous
			m_State |= (unsigned char)flag; // set current state
		}

		inline bool			IsRaised() const { return m_State == CMD_ST_RAISED; }
		inline bool			IsHolding() const { return m_State == CMD_ST_HOLD; }
		inline bool			IsCanceled() const{ return m_State == CMD_ST_CANCELED; }
		inline bool			IsUnused() const { return m_State == CMD_ST_UNUSED; }
		inline bool			HasChanged() const { return ( ( m_State & 0xF0 ) >> 4 ) != ( m_State & 0x0F ); }
	private:
		unsigned char		m_State;		/*!< Holding current and previous state of button */
		const char*			m_Name;		/*!< Name of the corresponding command */
	};

	enum KeyCode;

	/*!
	* Input singleton responsible for updating registered commands
	*/
	class Input : public Singleton<Input>
	{
		typedef std::pair<KeyCode, Command>		CommandsPair;
		typedef std::map<KeyCode, Command>		MapCommandsPerID;

		SINGLETON( Input )

		virtual void OnInitialize();

		virtual void OnDestroy();
	public:

		void			Update();
		bool			AddCommand( const char* name, KeyCode key, Command** outCommand );
		const Command&	GetCommand( KeyCode key ) const;

	
	private:
		MapCommandsPerID	m_Commands;

	};


enum KeyCode
{
	KEY_ESCAPE          = 0x01,
	KEY_1               = 0x02,
	KEY_2               = 0x03,
	KEY_3               = 0x04,
	KEY_4               = 0x05,
	KEY_5               = 0x06,
	KEY_6               = 0x07,
	KEY_7               = 0x08,
	KEY_8               = 0x09,
	KEY_9               = 0x0A,
	KEY_0               = 0x0B,
	KEY_MINUS           = 0x0C,
	KEY_EQUALS          = 0x0D,
	KEY_BACK            = 0x0E,
	KEY_TAB             = 0x0F,
	KEY_Q               = 0x10,
	KEY_W               = 0x11,
	KEY_E               = 0x12,
	KEY_R               = 0x13,
	KEY_T               = 0x14,
	KEY_Y               = 0x15,
	KEY_U               = 0x16,
	KEY_I               = 0x17,
	KEY_O               = 0x18,
	KEY_P               = 0x19,
	KEY_LBRACKET        = 0x1A,
	KEY_RBRACKET        = 0x1B,
	KEY_RETURN          = 0x1C,
	KEY_LCONTROL        = 0x1D,
	KEY_A               = 0x1E,
	KEY_S               = 0x1F,
	KEY_D               = 0x20,
	KEY_F               = 0x21,
	KEY_G               = 0x22,
	KEY_H               = 0x23,
	KEY_J               = 0x24,
	KEY_K               = 0x25,
	KEY_L               = 0x26,
	KEY_SEMICOLON       = 0x27,
	KEY_APOSTROPHE      = 0x28,
	KEY_GRAVE           = 0x29,
	KEY_LSHIFT          = 0x2A,
	KEY_BACKSLASH       = 0x2B,
	KEY_Z               = 0x2C,
	KEY_X               = 0x2D,
	KEY_C               = 0x2E,
	KEY_V               = 0x2F,
	KEY_B               = 0x30,
	KEY_N               = 0x31,
	KEY_M               = 0x32,
	KEY_COMMA           = 0x33,
	KEY_PERIOD          = 0x34,
	KEY_SLASH           = 0x35,
	KEY_RSHIFT          = 0x36,
	KEY_MULTIPLY        = 0x37,
	KEY_LMENU           = 0x38,
	KEY_SPACE           = 0x39,
	KEY_CAPITAL         = 0x3A,
	KEY_F1              = 0x3B,
	KEY_F2              = 0x3C,
	KEY_F3              = 0x3D,
	KEY_F4              = 0x3E,
	KEY_F5              = 0x3F,
	KEY_F6              = 0x40,
	KEY_F7              = 0x41,
	KEY_F8              = 0x42,
	KEY_F9              = 0x43,
	KEY_F10             = 0x44
};
}
